#include "tim.h"

volatile uint32_t uwTick = 0;
volatile uint32_t clock_time = 0;

//M0
void TIM0_Init(void){
    rcu_periph_clock_enable(RCU_TIMER0);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); //168MHz

    timer_parameter_struct timer_initpara;
    timer_oc_parameter_struct timer_ocintpara;
    timer_break_parameter_struct timer_breakpara;

    timer_struct_para_init(&timer_initpara);
    timer_channel_output_struct_para_init(&timer_ocintpara);
    timer_break_struct_para_init(&timer_breakpara);

    timer_deinit(TIMER0);
    /* TIMER0 configuration */
    timer_initpara.prescaler         = 0;
    timer_initpara.alignedmode       = TIMER_COUNTER_CENTER_BOTH;
    timer_initpara.period            = TIM_0_7_PERIOD_CLOCKS;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = TIM_0_7_RCR;
    timer_init(TIMER0,&timer_initpara);

    /* CH0/CH0N,CH1/CH1N and CH2/CH2N configuration in timing mode */
    timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
    timer_ocintpara.outputnstate = TIMER_CCXN_ENABLE;
    timer_ocintpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
    timer_ocintpara.ocidlestate  = TIMER_OCN_IDLE_STATE_LOW;
    timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;

    timer_channel_output_config(TIMER0,TIMER_CH_0,&timer_ocintpara);
    timer_channel_output_config(TIMER0,TIMER_CH_1,&timer_ocintpara);
    timer_channel_output_config(TIMER0,TIMER_CH_2,&timer_ocintpara);
    //timer_channel_output_config(TIMER0,TIMER_CH_3,&timer_ocintpara);
    //CH0/CH0N
    timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,0);
    timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM1);
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_0,TIMER_OC_SHADOW_ENABLE);
    //CH1/CH1N
    timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_1,0);
    timer_channel_output_mode_config(TIMER0,TIMER_CH_1,TIMER_OC_MODE_PWM1);
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_1,TIMER_OC_SHADOW_ENABLE);
    //CH2/CH2N
    timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_2,0);
    timer_channel_output_mode_config(TIMER0,TIMER_CH_2,TIMER_OC_MODE_PWM1);
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_2,TIMER_OC_SHADOW_ENABLE);
    /* automatic output disable, break, dead time and lock configuration*/
    timer_breakpara.runoffstate     = TIMER_ROS_STATE_ENABLE;
    timer_breakpara.ideloffstate    = TIMER_IOS_STATE_ENABLE;
    timer_breakpara.protectmode     = TIMER_CCHP_PROT_OFF;
    timer_breakpara.deadtime        = TIM_0_7_DEADTIME_CLOCKS;
    timer_breakpara.breakstate      = TIMER_BREAK_DISABLE;
    timer_breakpara.breakpolarity   = TIMER_BREAK_POLARITY_HIGH;
    timer_breakpara.outputautostate = TIMER_OUTAUTO_DISABLE;
    timer_break_config(TIMER0,&timer_breakpara);
    
    timer_primary_output_config(TIMER0,DISABLE);
    /* select the master slave mode */
    timer_master_slave_mode_config(TIMER0,TIMER_MASTER_SLAVE_MODE_DISABLE);
    /* TIMER0 update event is used as trigger output */
    timer_master_output_trigger_source_select(TIMER0,TIMER_TRI_OUT_SRC_UPDATE);
    //timer_interrupt_enable(TIMER0,TIMER_INT_UP);
    nvic_irq_enable(TIMER0_UP_TIMER9_IRQn,0,0);
    timer_disable(TIMER0);
}
//Brake
void TIM1_Init(void){

}
//Encoder
void TIM2_Init(void){
    rcu_periph_clock_enable(RCU_TIMER2);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);

    timer_ic_parameter_struct timer_icinitpara;
    timer_parameter_struct timer_initpara;

    timer_channel_input_struct_para_init(&timer_icinitpara);
    timer_struct_para_init(&timer_initpara);
    //失能
    timer_deinit(TIMER2);
    //参数初始化
    timer_initpara.prescaler         = 0;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 0xFFFF;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER2,&timer_initpara);

    //输入参数初始化
    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter    = 0x4;
    timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
    timer_input_capture_config(TIMER2,TIMER_CH_1,&timer_icinitpara);

    //编码器模式
    timer_quadrature_decoder_mode_config(TIMER2,TIMER_ENCODER_MODE2,TIMER_IC_POLARITY_BOTH_EDGE,TIMER_IC_POLARITY_BOTH_EDGE);
    timer_auto_reload_shadow_enable(TIMER2);
}

void TIM3_Init(void){
    rcu_periph_clock_enable(RCU_TIMER3);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);

    timer_ic_parameter_struct timer_icinitpara;
    timer_parameter_struct timer_initpara;

    timer_channel_input_struct_para_init(&timer_icinitpara);
    timer_struct_para_init(&timer_initpara);
    //失能
    timer_deinit(TIMER3);
    //参数初始化
    timer_initpara.prescaler         = 0;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 0xFFFF;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER3,&timer_initpara);

    //输入参数初始化
    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter    = 0x4;
    timer_input_capture_config(TIMER3,TIMER_CH_0,&timer_icinitpara);
    timer_input_capture_config(TIMER3,TIMER_CH_1,&timer_icinitpara);

    //编码器模式
    timer_quadrature_decoder_mode_config(TIMER3,TIMER_ENCODER_MODE2,TIMER_IC_POLARITY_BOTH_EDGE,TIMER_IC_POLARITY_BOTH_EDGE);
    timer_auto_reload_shadow_enable(TIMER3);
}

void TIM4_Init(void){
    rcu_periph_clock_enable(RCU_TIMER4);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);

    timer_ic_parameter_struct timer_icinitpara;
    timer_parameter_struct timer_initpara;

    timer_channel_input_struct_para_init(&timer_icinitpara);
    timer_struct_para_init(&timer_initpara);

    timer_deinit(TIMER4);
    /* TIMER4 configuration */
    timer_initpara.prescaler         = 84/4-1;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 0xFFFF;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER4,&timer_initpara);

    /* TIMER4 configuration */
    /* TIMER4 CH0 PWM input capture configuration */
    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter    = 0x00;
    timer_input_pwm_capture_config(TIMER4,TIMER_CH_0,&timer_icinitpara);

    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_FALLING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_INDIRECTTI;
    timer_input_pwm_capture_config(TIMER4,TIMER_CH_1,&timer_icinitpara);

    /* slave mode selection: TIMER4 */
    timer_input_trigger_source_select(TIMER4,TIMER_SMCFG_TRGSEL_CI0FE0);
    timer_slave_mode_select(TIMER4,TIMER_SLAVE_MODE_RESTART);

    /* select the master slave mode */
    timer_master_slave_mode_config(TIMER4,TIMER_MASTER_SLAVE_MODE_ENABLE);

   /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER4);
    /* clear channel 0 interrupt bit */
    timer_interrupt_flag_clear(TIMER4,TIMER_INT_CH0);
    timer_interrupt_flag_clear(TIMER4,TIMER_INT_CH1);
    /* channel 0 interrupt enable */
    timer_interrupt_enable(TIMER4,TIMER_INT_CH0);
    timer_interrupt_enable(TIMER4,TIMER_INT_CH1);

    nvic_irq_enable(TIMER4_IRQn,6,0);
    timer_enable(TIMER4);
}

void TIM7_Init(void){
    rcu_periph_clock_enable(RCU_TIMER7);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); //168MHz

    timer_parameter_struct timer_initpara;
    timer_oc_parameter_struct timer_ocintpara;
    timer_break_parameter_struct timer_breakpara;

    timer_struct_para_init(&timer_initpara);
    timer_channel_output_struct_para_init(&timer_ocintpara);
    timer_break_struct_para_init(&timer_breakpara);

    timer_deinit(TIMER7);
    /* TIMER7 configuration */
    timer_initpara.prescaler         = 0;
    timer_initpara.alignedmode       = TIMER_COUNTER_CENTER_BOTH;
    timer_initpara.period            = TIM_0_7_PERIOD_CLOCKS;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = TIM_0_7_RCR;
    timer_init(TIMER7,&timer_initpara);
    /* CH0/CH0N,CH1/CH1N,CH2/CH2N configuration in timing mode */
    timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
    timer_ocintpara.outputnstate = TIMER_CCXN_ENABLE;
    timer_ocintpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
    timer_ocintpara.ocidlestate  = TIMER_OCN_IDLE_STATE_LOW;
    timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
    timer_channel_output_config(TIMER7,TIMER_CH_0,&timer_ocintpara);
    timer_channel_output_config(TIMER7,TIMER_CH_1,&timer_ocintpara);
    timer_channel_output_config(TIMER7,TIMER_CH_2,&timer_ocintpara);
   //CH0/CH0N
    timer_channel_output_pulse_value_config(TIMER7,TIMER_CH_0,0);
    timer_channel_output_mode_config(TIMER7,TIMER_CH_0,TIMER_OC_MODE_PWM1);
    timer_channel_output_shadow_config(TIMER7,TIMER_CH_0,TIMER_OC_SHADOW_ENABLE);
    //CH1/CH1N
    timer_channel_output_pulse_value_config(TIMER7,TIMER_CH_1,0);
    timer_channel_output_mode_config(TIMER7,TIMER_CH_1,TIMER_OC_MODE_PWM1);
    timer_channel_output_shadow_config(TIMER7,TIMER_CH_1,TIMER_OC_SHADOW_ENABLE);
    //CH2/CH2N
    timer_channel_output_pulse_value_config(TIMER7,TIMER_CH_2,0);
    timer_channel_output_mode_config(TIMER7,TIMER_CH_2,TIMER_OC_MODE_PWM1);
    timer_channel_output_shadow_config(TIMER7,TIMER_CH_2,TIMER_OC_SHADOW_ENABLE);

    /* automatic output disable, break, dead time and lock configuration*/
    timer_breakpara.runoffstate     = TIMER_ROS_STATE_ENABLE;
    timer_breakpara.ideloffstate    = TIMER_IOS_STATE_ENABLE;
    timer_breakpara.protectmode     = TIMER_CCHP_PROT_OFF;
    timer_breakpara.deadtime        = TIM_0_7_DEADTIME_CLOCKS;
    timer_breakpara.breakstate      = TIMER_BREAK_DISABLE;
    timer_breakpara.breakpolarity   = TIMER_BREAK_POLARITY_HIGH;
    timer_breakpara.outputautostate = TIMER_OUTAUTO_DISABLE;
    timer_break_config(TIMER7,&timer_breakpara);
    
    timer_primary_output_config(TIMER7,DISABLE);
    /* select the master slave mode */
    timer_master_slave_mode_config(TIMER7,TIMER_MASTER_SLAVE_MODE_DISABLE);
    /* TIMER7 update event is used as trigger output */
    timer_master_output_trigger_source_select(TIMER7,TIMER_TRI_OUT_SRC_UPDATE);
    nvic_irq_enable(TIMER7_UP_TIMER12_IRQn,0,0);
    timer_disable(TIMER7);
}
void TIM8_Init(void){
    rcu_periph_clock_enable(RCU_TIMER8);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);

    timer_ic_parameter_struct timer_icinitpara;
    timer_parameter_struct timer_initpara;

    timer_channel_input_struct_para_init(&timer_icinitpara);
    timer_struct_para_init(&timer_initpara);

    timer_deinit(TIMER8);
    /* TIMER8 configuration */
    timer_initpara.prescaler         = 84/4-1;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 0xFFFF;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER8,&timer_initpara);

    /* TIMER8 configuration */
    /* TIMER8 CH0 PWM input capture configuration */
    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter    = 0x00;
    timer_input_pwm_capture_config(TIMER8,TIMER_CH_0,&timer_icinitpara);

    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_FALLING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_INDIRECTTI;
    timer_input_pwm_capture_config(TIMER8,TIMER_CH_1,&timer_icinitpara);
    /* slave mode selection: TIMER8 */
    timer_input_trigger_source_select(TIMER8,TIMER_SMCFG_TRGSEL_CI0FE0);
    timer_slave_mode_select(TIMER8,TIMER_SLAVE_MODE_RESTART);

    /* select the master slave mode */
    timer_master_slave_mode_config(TIMER8,TIMER_MASTER_SLAVE_MODE_ENABLE);

   /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER8);
    /* clear channel 0 interrupt bit */
    timer_interrupt_flag_clear(TIMER8,TIMER_INT_CH0);
    timer_interrupt_flag_clear(TIMER8,TIMER_INT_CH1);
    /* channel 0 interrupt enable */
    timer_interrupt_enable(TIMER8,TIMER_INT_CH0);
    timer_interrupt_enable(TIMER8,TIMER_INT_CH1);

    nvic_irq_enable(TIMER0_BRK_TIMER8_IRQn,6,0);
    timer_enable(TIMER8);
}
void TIM12_Init(void){
    rcu_periph_clock_enable(RCU_TIMER12);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);

    timer_parameter_struct timer_initpara;
    timer_struct_para_init(&timer_initpara);

    timer_deinit(TIMER12);

    timer_initpara.prescaler         = 0;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = (2 * TIM_0_7_PERIOD_CLOCKS * (TIM_0_7_RCR+1)) * ((float)TIM_APB1_CLOCK_HZ / (float)TIM_0_7_CLOCK_HZ) - 1;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_init(TIMER12,&timer_initpara);
}

void TIM13_Init(void){
    rcu_periph_clock_enable(RCU_TIMER13);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);

    timer_parameter_struct timer_initpara;
    
    //timer_deinit(TIMER13);
    timer_struct_para_init(&timer_initpara);
    /* TIMER13 configuration */
    timer_initpara.prescaler         = 1000 - 1;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 168 - 1;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER13,&timer_initpara);

    timer_auto_reload_shadow_enable(TIMER13);
    timer_interrupt_enable(TIMER13,TIMER_INT_UP);
    //timer_interrupt_enable(TIMER13,TIMER_INT_TRG);
    timer_interrupt_flag_clear(TIMER13,TIMER_INT_FLAG_UP);
    nvic_irq_enable(TIMER7_TRG_CMT_TIMER13_IRQn,0,0);   //中断函数使能
    timer_enable(TIMER13);
}



/*!
    \brief      delay a time in milliseconds
    \param[in]  count: count in milliseconds
    \param[out] none
    \retval     none
*/
void delay_1ms(uint32_t count)
{
    clock_time = count;
    while(clock_time){
    }
}

/*!
    \brief      delay decrement
    \param[in]  none
    \param[out] none
    \retval     none
*/
void delay_decrement(void)
{
    uwTick++;
    clock_time--;
}

uint32_t TIM_BASE_GetTick(void){
    return uwTick;
}

// @brief: Returns number of microseconds since system startup
uint32_t micros(void) {
    register uint32_t ms, cycle_cnt;
    do {
        ms = TIM_BASE_GetTick();
        cycle_cnt = TIMER_CNT(TIM_TIME_BASE);
     } while (ms != TIM_BASE_GetTick()); 

    return (ms * 1000) + cycle_cnt;
}

void delay_1us(uint32_t us)
{
    uint32_t start = micros();
    while (micros() - start < (uint32_t) us) {
        __ASM("nop");
    }
}